﻿package org.kisekiproject.components.ui {
	import flash.display.MovieClip;
	import flash.display.FrameLabel;
	import flash.events.Event;

	/**
	 * Manage animated state transitions for movie clips.
	 */
	public class MovieClipStateManager
	{
		private var _clip:MovieClip;
		private var _activeState:String;
		private var _targetState:String;

		/**
		 * Constructor.
		 */
		public function MovieClipStateManager(clip:MovieClip)
		{
			_clip=clip;

			if (_clip.currentLabels[0])
				currentState=_clip.currentLabels[0].name;

			else
				_clip.gotoAndStop(1);

			_clip.addEventListener(Event.ADDED_TO_STAGE,onClipAddedToStage);
		}

		/**
		 * added to stage.
		 */
		private function onClipAddedToStage(e:Event):void {
			_activeState=_targetState;

			//trace("clip added to stage "+_clip.name+" active="+_activeState);
			_clip.gotoAndStop(1);
			_clip.gotoAndStop(2);
			_clip.gotoAndStop(_activeState);
			_clip.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
		}

		/**
		 * Set state without animation.
		 */
		public function installState(value:String):void {
			_clip.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
			_activeState=_targetState=value;
			_clip.gotoAndStop(value);
		}

		/**
		 * Set current state.
		 */
		public function set currentState(value:String):void {
			//trace("setting state for "+_clip.name+": "+value);
			if (labelExists(getTransitionLabel(_activeState,value)))
			{
				_targetState=value;
				_clip.gotoAndPlay(getTransitionLabel(_activeState,value));
				_clip.addEventListener(Event.ENTER_FRAME,onEnterFrame);
			}

			else
			{
				_clip.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
				_activeState=_targetState=value;
				_clip.gotoAndStop(value);
			}
		}

		/** Enter frame.
		 *
		 */
		private function onEnterFrame(e:Event):void {
			var current:String=getCurrentFrameLabelSafe(_clip);

			//trace("enter frame, currentFrameLabel="+current);
			if (current!=null && current!=getTransitionLabel(_activeState,_targetState))
			{
				_activeState=_targetState;
				_clip.gotoAndStop(_activeState);
				_clip.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
			}
		}

		/**
		 * Create transition label.
		 */
		private function getTransitionLabel(from:String, to:String):String {
			return from+"-"+to;
		}

		/**
		 *
		 */
		private function labelExists(l:String):Boolean {
			for each (var fl:FrameLabel in _clip.currentLabels)
				if (fl.name==l)
					return true;

			return false;
		}

		/**
		 * Flash player 9 safe version of currentFrameLabel
		 */
		private static function getCurrentFrameLabelSafe(c:MovieClip):String {
			for each (var fl:FrameLabel in c.currentLabels)
				if (fl.frame==c.currentFrame)
					return fl.name;

			return undefined;
		}
	}
}